Jx.declare('Jx.event.Operation', {

	$extend: 'Jx.lib.Operation',

	$category: 'event.operation.default',

	$helpers: {

		'Fn': 'Jx.lib.Function'

	},

	$accessors: {

		'returnValue': true,

		'type': undefined,

		'target': undefined,

		'currentTarget': undefined,

		'timestamp': undefined,

		'defaultPrevented': false,

		'bubbles': true

	},

	$actions: [ 'stopPropagation', 'preventDefault', 'stopRunningHandler', 'startRunningHandler' ],

	deferred: undefined,

	propagationChain: undefined,

	ended: undefined,

	__ref_TargetClass: 'Jx.event.Observable',

	constructor: function(){

		this.deferred = [];

		this.propagationChain = [];

		this.$super(arguments);

	},

	onConstruct: function( type ){

		this.setTimestamp( new Date() );

		this.setType( type );

		this.$super(arguments);

	},

	onDestroy: function(){

		this.$super();

	},

	allowSetTarget: function(o, observable){

		var valid = o.valid = Jx.instanceOf(observable, this.__ref_TargetClass );

		if (valid){

			o.value = observable;

		}

	},

	onSetTarget: function(o, observable){

		//-- create propagation chain
		var chain = this.propagationChain,

			ob = o.data.target = o.value,

			c = 0;

		// remove current
		chain.splice(0, chain.length);

		for(ob = ob.event.getBubbleTarget(); ob; ob = ob.event.getBubbleTarget()){

			chain.unshift( ob );

		}

	},

	allowSetCurrentTarget: function(o, observable){

		this.allowSetTarget(o, observable);

	},

	allowSetDefaultPrevented: function(o, prevent){

		o.value = prevent !== false;

	},

	allowSetBubbles: function(o, propagate){

		o.value = propagate !== false;

	},

	allowSetType: function(o, type){

		o.valid = Jx.isString(type) && !!type;

	},

	onPreventDefault: function(o){

		this.setDefaultPrevented(true);

	},

	onStopPropagation: function(o){

		this.setBubbles(true);

	},

	getNextInPropagateChain: function(){

		var allow = this.getBubbles(),

			chain = this.propagationChain,

			len = chain.length;

		//-- remove all
		if (!allow && len){

			chain.splice(0, len);

		//-- find non-destroyed observable
		} else if (allow){

			for(var observable; len--;){

				observable = chain.splice(len, 1)[0];

				if (!observable.destroyed){

					return observable;

				}

			}

		}

		return void(0);

	}

});
